(function ($) {
    console.warn("NumberExtensionsByJQuery.js version: 2022-10-20 17:16:32")

    if (Number.render) {
        return;
    }

    /**
     * 绑定事件(可以正确处理重复绑定的问题)
     * @param {any} ele         需绑定事件的元素
     * @param {any} eventName   事件名称
     * @param {any} func        事件行为
     */
    function bindEvent(ele, eventName, func) {
        var n = "#" + eventName + "#"
        func = func.bind(ele);
        ele.removeEventListener(eventName, ele[n]);
        ele[n] = func
        ele.addEventListener(eventName, ele[n]);
    }

    /**
     * 触发事件
     * @param {any} ele         需触发事件的元素
     * @param {any} eventName   事件名称
     */
    function triggerEvent(ele, eventName) {
        var func = ele["#" + eventName + "#"];
        func && func();
    }


    /**
     * 渲染input元素
     * @param {any} input
     */
    function renderInput(input) {
        bindEvent(input, "change", function () {
            var style = parseNumberConfig(this, "style");
            var unit = parseNumberConfig(this, "unit");
            if ($(this).is("[number-strict]")) {
                var number = Number.scale(this.value || 0, style, unit);
                if (number == null) {
                    this.value = this.historyValue == null ? "" : this.historyValue;
                } else {
                    var min = Number.parse($(this).attr("number-min"));
                    var max = Number.parse($(this).attr("number-max"));
                    if (min != null && number < min) {
                        number = min;
                    } else if (max != null && number > max) {
                        number = max;
                    }
                    this.historyValue = this.value = number.format(style, unit);
                }
            } else {
                var value = Number.scaleformat(this.value, style, unit);
                if (value != null) {
                    this.value = value;
                }
            }
        });
        bindEvent(input, "focus", function () {
            var number = Number.parse(this.value);
            if (number != null) {
                this.value = number || "";
            }
        });
        bindEvent(input, "blur", function () {
            var style = parseNumberConfig(this, "style");
            var unit = parseNumberConfig(this, "unit");
            var value = Number.format(this.value, style, unit);
            if (value != null) {
                this.historyValue = this.value = value;
            }
        });

        var style = parseNumberConfig(input, "style");
        var unit = parseNumberConfig(input, "unit");
        var config = Number.getConfig(style, unit);
        if (config.align) {
            $(input).css({ "text-align": config.align });
        }
        triggerEvent(input, "blur");
    }

    /**
     * 渲染除input以外的元素
     * @param {any} ele
     */
    function renderInnerText(ele) {
        var style = parseNumberConfig(ele, "style");
        var unit = parseNumberConfig(ele, "unit");
        var format = Number.format(ele.innerText, style, unit);
        if (format != null) {
            ele.innerText = format;
        }
        var config = Number.getConfig(style, unit);

        if (config.align) {
            $(ele).css({ "text-align": config.align });
        }

    }

    /**
     * 获取指定的配置
     * @param {any} ele  页面元素
     * @param {any} type "style" 或 "unit"
     */
    function parseNumberConfig(ele, type) {
        var attr = "number-" + type;
        var value = $(ele).attr(attr);
        if (value) {
            return value;
        }
        if ($(ele).is(getSelector())) {
            var className = $(ele).attr("class");
            if (className) {
                return className.split(' ').filter(function (x) { return x.startsWith(attr) }).map(x => x.substring(attr.length + 1))[0];
            }
        }
    }

    /**
     * 获取number-style相关页面元素的选择器
     */
    function getSelector() {
        var classNames = ["[number-style]"];
        var keys = Object.keys(localStorage).filter(x => x.startsWith("numberconfig:") && localStorage[x].charAt(0) === '{').map(x => x.split(":")[1]);
        for (var key of keys) {
            classNames.push(".number-style-" + key);
        }
        return classNames.join(",");
    }


    var jqueryVal = $().val;
    var jqueryText = $().text;

    // 扩展jQuery val取值逻辑
    $.fn.extend({
        val: function () {
            var style = parseNumberConfig(this[0], "style");
            var value = jqueryVal.apply(this, arguments);
            if (style == null) {
                return value;
            }
            if (this.length == 1 && this.is(getSelector())) {
                if (value === this) {
                    var unit = parseNumberConfig(this[0], "unit");
                    this[0].value = Number.format(this[0].value, style, unit);
                } else {
                    var number = Number.parse(value);
                    if (number != null) {
                        return number.toString();
                    }
                }
            }
            return value;
        },
        text: function () {
            var style = parseNumberConfig(this[0], "style");
            var value = jqueryText.apply(this, arguments);
            if (style == null) {
                return value;
            }
            if (this.length == 1 && this.is(getSelector())) {
                if (value === this) {
                    var unit = parseNumberConfig(this[0], "unit");
                    this[0].innerText = Number.format(this[0].innerText, style, unit);
                } else {
                    var number = Number.parse(value);
                    if (number != null) {
                        return number.toString();
                    }
                }
            }
            return value;
        },
    });


    /**
     * 渲染页面所有 number-style 元素
     */
    Number.render = function () {
        $(getSelector()).each(function (_, ele) {
            if ($(ele).is("input")) {
                renderInput(ele);
            } else {
                renderInnerText(ele);
            }
        });
    }

})(jQuery);